package com.fingard.dsp.bankset;

import com.fingard.FGBiz;
import com.fingard.db.ConnSet;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directConfig.ListenerSet;
import com.fingard.dsp.bank.directConfig.TaskTimerSet;
import com.fingard.dsp.bank.reqrespobj.PacketType;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;
import com.fingard.text.AESHelper;
import com.fingard.text.MD5SaltHelper;
import com.fingard.text.StringHelper;
import com.fingard.threading.ResetEvent;
import com.fingard.xml.XElement;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.lang.reflect.Field;
import java.net.Socket;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class BankFront {

    /**机构代码Name*/
    public static final String NameOrg = "org";
    /**私钥路径Name*/
    public static final String NameOwnKeyStorePath = "ownKeyStorePath";
    /**私钥密码Name*/
    public static final String NameOwnKeyPassword = "ownKeyPassword";
    public static String dbSelectSql = "SELECT\n" +
            "\tbi. code bicode,\n" +
            "\tbi. name biname,\n" +
            "\tbi.entity bicorp,\n" +
            "\tbi.system_code bigroup,\n" +
            "\tbi.pay_queue_count bipqc,\n" +
            "\tbi.pay_qry_queue_count bipqqc,\n" +
            "\tbi.else_queue_count bieqc,\n" +
            "\tbf.urid urid,\n" +
            "\tbf.code bfcode,\n" +
            "\tbf.name bfname,\n" +
            "\tbf.remote_ip bfip,\n" +
            "\tbf.serv_port bfservp,\n" +
            "\tbf.secu_port bfsecup,\n" +
            "\tbf.file_port bffilep,\n" +
            "\tbf.pay_sync_count bfpsc,\n" +
            "\tbf.query_sync_count bfqsc,\n" +
            "\tbf.priority bfp,\n" +
            "\tbf.supp_trans_type bfsupp,\n" +
            "\tbf.non_supp_trans_type bfnon,\n" +
            "\tbfs.param_type bfstype,\n" +
            "\tbfs.param_key bfskey,\n" +
            "\tbfs.param_value bfsvalue\n" +
            "FROM\n" +
            "\ttbl_dspcl_bank_front bf\n" +
            "INNER JOIN tbl_dspcl_bank_info bi ON bf.bank_info_id = bi.urid\n" +
            "AND bi.active_flag = 1\n" +
            "LEFT JOIN tbl_dspcl_bank_front_set bfs ON bfs.bank_front_id = bf.urid\n" +
            "AND bfs.active_flag = 1\n" +
            "WHERE\n" +
            "\tbf.active_flag = 1";
    /**URID*/
    public String urid = "";
    /**所属线路代码，如ICBC02*/
    public String bankCode = "";
    /**所属法人组织/管理组织，如5000001*/
    public String corporation = "";
    /**所属账户分组*/
    public String group = "";
    /**所属租户，适用云平台租户*/
    public String tenant = "";
    /**代码*/
    public String code = "";
    /**名称*/
    public String name = "";
    /**服务IP*/
    public String serverIP = "";
    /**服务端口*/
    public String serverPort = "";
    /**签名端口*/
    public String signPort = "";

    /**机构号、组织代码、CIS号等*/
    public String org = "";
    
    /** 协议号 */
    public String protocolNo = "";

    /**公司编号*/
    public String corpNo = "";
    /**证书key ID*/
    public String keyID = "";
    /**登录名*/
    public String loginName = "";

    /**对方公钥文件地址*/
    public String oppCertFilePath;
    
	/**本方证书（含私钥）*/
	public String ownKeyStorePath = "";
	/**本方证书（含私钥）密码*/
	public String ownKeyPassword = "";
	
	/**xml格式保存的本方私钥*/
	public String ownPrivateKeyXmlFilePath = "";
	
	/**xml格式保存的对方公钥*/
	public String oppPublicKeyXmlFilePath = "";

    /**交易服务地址*/
    public String serverURL = "";

    /**签名服务地址*/
    public String signURL = "";
    /**密码*/
    public String loginPasswd = "";
    /**操作员*/
    public String operator = "";
    /**终端号*/
    public String termid = "";//代表一台企业前置机
    
    /**服务方代码，接收方代码，一般在登录时用到*/
    public String serverCode = "";

    //下面用于需要登录前置机维持会话的情况
    /**会话token*/
    public volatile String token = "";
    /**最后登录时间*/
    public volatile Date lastLoginTime;
    /**最后访问时间*/
    public volatile Date lastVisitTime;
    /**登录失败次数*/
    public int loginFailCount = 0;
    /**登录标识*/
    public volatile String loginFlag = "";
    
    /**前置机登录会话（token）是否从 MasterHost（主控DSP）同步*/
    public boolean syncTokenFromMasterHost = false;

    public String bkTransFolder = "";
    public String bkPayFolder = "";
    public String bkRecFolder = "";
    public String bkQryPayFolder = "";
    public String bkQryRecFolder = "";
    public String bkQryEleFolder ="";
    public String folderForRemoteHost = "";
    public boolean isGettingToken = false;
    /**
     * 存取前置机文件的方式
     */
    public String accessBkFileMode = "";

    /**
     * 前置机上部署的DSP文件服务地址
     */
    public String dspFileServer = "";
    public String serverUpload = "";
    public String serverDownload = "";
    //共享文件夹的用户名
    public String userName = "";
    //共享文件夹的密码
    public String userPassword = "";
    /**
     * 银行前置机存回单文件的目录
     */
    public String bankReceiptMainDir = "";
    //public String dbDriver ="";
    //public String dbUrl ="";
    //public String dbUser ="";
    //public String dbPassword ="";
    public BankFrontStatus frontStatus = null;
    public String filePort = "";
    public int elseQueuecount = 0;
    public int payQueryQueueCount = 0;
    public int payQueueCount = 0;
    public int frontPriority = 0;
    /**
     * 查询最大并发数
     */
    public int frontQueryMaxCcCount = 0;
    /**
     * 支付最大并发数
     */
    public int frontPayMaxCcCount = 0;
    /**
     * 前置检测等级，空或1-通讯 2-余额
     */
    public String checkLevel="";
    /**
     * 电票查询最大并发数
     */
    public int frontEleQueryMaxCcCount = 0;
    /**
     * 电票申请最大并发数
     */
    public int frontEleMaxCcCount = 0;
    public Map<String, Map<String, String>> frontSet = null;
    /**
     * 自定义键值对保存对象，用于需要按前置机临时存储信息的情况，如浦发额外授权的会话
     */
    public HashMap<String, String> customMap = null;
    /**自定义对象，用于存放需按前置机缓存的对象*/
    public HashMap<String, Object> customObjects = null;
    /**
     * 存放需要解密的数据
     */
    public Map<String, String> decrypt = new HashMap<String, String>();
    //private BankFront bankFront;
    /**线程同步器*/
    public ResetEvent resetEvent = null;
    public String supportTransType = "";
    public String nonSupportTransType = "";
    public HashMap<String, ListenerSet> hashListenerSet = null;
    public HashMap<String, TaskTimerSet> hashTimerSet = null;
    HashMap<String, String> mapSupport = null;
    HashMap<String, String> mapNonSupport = null;
    /**
     * 当前电票查询并发数
     */
    private AtomicInteger eleQryConcurrentNumNow = new AtomicInteger();
    /**
     * 当前电票申请并发数
     */
    private AtomicInteger eleConcurrentNumNow = new AtomicInteger();
    /**
     * 当前支付并发数
     */
    private AtomicInteger payConcurrentNumNow = new AtomicInteger();
    /**
     * 当前查询并发数
     */
    private AtomicInteger qryConcurrentNumNow = new AtomicInteger();
    private HashMap<String, FtpSet> hashFtpSet = null;
    private Map<String, Object[]> hashToken = null;
    private HashMap<String, ConnSet> hashConnSet = null;
    private HashMap<String, String> hashServerURL = null;
    /**
     * 将key value的配置都存储在HashMap中，key为name-for
     */
    private HashMap<String, String> mapStrValueByFor = null;
    
    public Object mutex1944;
    public Object mutex9144;
    public Object mutex7516;
    public Object mutexQryRefund;
    public Object mutexNotify;

    public String useDirectchannelJarFile;

    public BankFront() {
        frontStatus = new BankFrontStatus();
        customMap = new HashMap<String, String>();
        customObjects = new HashMap<String, Object>();
        resetEvent = new ResetEvent();
        mutex9144 = new Object();
        mutex1944 = new Object();
        mutex7516 = new Object();
        mutexQryRefund = new Object();
        mutexNotify = new Object();
    }
    
    public void putCustomObjects(String pKey, Object pVal){
    	synchronized (customObjects) {
    		customObjects.put(pKey, pVal);
    	}
    }

    public String getAccessBkFileModeLowerCase() {
        if (StringHelper.hasAnyChar(accessBkFileMode)) {
            return accessBkFileMode.toLowerCase();
        }
        return "";
    }

    /**
     * 获取当前支付并发数
     */
    public int getPayConcurrent() {
        return payConcurrentNumNow.get();
    }
    
    /**
     * 支付并发+1
     */
    public int plusPayConcurrent() {
        int ccNum = payConcurrentNumNow.incrementAndGet();
        return ccNum;
    }
    
    /**
     * 支付并发-1
     */
    public int minusPayConcurrent() {
        int ccNum = payConcurrentNumNow.decrementAndGet();
        return ccNum;
    }
    
    /**
     * 获取当前电票申请并发数
     */
    public int getEleConcurrent() {
        return eleConcurrentNumNow.get();
    }

    /**
     * 电票申请并发+1
     */
    public int plusEleConcurrent() {
        int ccNum = eleConcurrentNumNow.incrementAndGet();
        return ccNum;
    }
    
    /**
     * 电票申请并发-1
     */
    public int minusEleConcurrent() {
        int ccNum = eleConcurrentNumNow.decrementAndGet();
        return ccNum;
    }

    /**
     * 获取当前查询并发数
     */
    public int getQryConcurrent() {
        return qryConcurrentNumNow.get();
    }

    /**
     * 查询并发+1
     */
    public int plusQryConcurrent() {
        int ccNum = qryConcurrentNumNow.incrementAndGet();
        return ccNum;
    }

    /**
     * 查询并发-1
     */
    public int minusQryConcurrent() {
        int ccNum = qryConcurrentNumNow.decrementAndGet();
        return ccNum;
    }

    /**
     * 获取当前电票查询并发数
     */
    public int getEleQryConcurrent() {
        return eleQryConcurrentNumNow.get();
    }

    /**
     * 电票查询并发+1
     */
    public int plusEleQryConcurrent() {
        int ccNum = eleQryConcurrentNumNow.incrementAndGet();
        return ccNum;
    }

    /**
     * 电票查询并发-1
     */
    public int minusEleQryConcurrent() {
        int ccNum = eleQryConcurrentNumNow.decrementAndGet();
        return ccNum;
    }

    /**
     * 并发数+1
     */
    public int plusConcurrent(ReqRespHeader p_header) {
        if (p_header.pckType == PacketType.Pay) {
            return plusPayConcurrent();
        } else {
            return plusQryConcurrent();
        }
    }

    /**
     * 并发数-1
     */
    public int minusConcurrent(ReqRespHeader p_header) {
        if (p_header.pckType == PacketType.Pay) {
            return minusPayConcurrent();
        } else {
            return minusQryConcurrent();
        }
    }

    /**
     * 分配资源，返回true并使用完之后，需要调用release()释放资源
     */
    public boolean allocate(ReqRespHeader p_header) {
        if (p_header.pckType == PacketType.Pay) {
            if (frontPayMaxCcCount > 0 && frontEleMaxCcCount <= 0) {//有并发数限制
                for (int i = 0; i < 3; i++) {//自旋3次，每次count 1000
                    int cc = payConcurrentNumNow.get();
                    if (cc < this.frontPayMaxCcCount) {
                        int newCcNum = cc + 1;
                        if (payConcurrentNumNow.compareAndSet(cc, newCcNum)) {
                            return true;
                        } else {
                            for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                continue;
                            }
                        }
                    }
                }
            }else if (this.frontPayMaxCcCount > 0) {//有并发数限制
                for (int i = 0; i < 5; i++) {//自旋5次，每次count 1000
                    int cc = this.eleConcurrentNumNow.get();
                    int dd = this.payConcurrentNumNow.get();
                    if (cc+ dd<this.frontPayMaxCcCount) {
                        //先抢占资源，然后在判断是否可以使用资源
                        int newDdNum = dd + 1;
                        if (payConcurrentNumNow.compareAndSet(dd, newDdNum)) {
                            if(newDdNum+this.eleConcurrentNumNow.get()<=this.frontPayMaxCcCount) {
                                return true;
                            }else {
                                payConcurrentNumNow.decrementAndGet();
                                for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                    continue;
                                }
                            }
                        } else {
                            for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                continue;
                            }
                        }
                    }
                }
            }else {//无并发数限制
                payConcurrentNumNow.incrementAndGet();
                return true;
            }
        } else if(p_header.pckType == PacketType.Ele){
            if (this.frontEleMaxCcCount > 0&& this.frontPayMaxCcCount>0) {//有并发数限制
                for (int i = 0; i < 3; i++) {//自旋3次，每次count 1000
                    int cc = this.eleConcurrentNumNow.get();
                    int dd = this.payConcurrentNumNow.get();
                    if (cc < this.frontEleMaxCcCount &&cc+ dd<this.frontPayMaxCcCount) {
                        //先抢占资源，然后在判断是否可以使用资源
                        int newCcNum = cc + 1;
                        if (eleConcurrentNumNow.compareAndSet(cc, newCcNum)) {
                            if(newCcNum+this.payConcurrentNumNow.get()<=this.frontPayMaxCcCount) {
                                return true;
                            }else {
                                eleConcurrentNumNow.decrementAndGet();
                                for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                    continue;
                                }
                            }
                        } else {
                            for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                continue;
                            }
                        }
                    }
                }
            }else if(this.frontEleMaxCcCount > 0){
                for (int i = 0; i < 3; i++) {//自旋3次，每次count 1000
                    int cc = this.eleConcurrentNumNow.get();
                    if (cc < this.frontEleMaxCcCount) {
                        int newCcNum = cc + 1;
                        if (eleConcurrentNumNow.compareAndSet(cc, newCcNum)) {
                            return true;
                        } else {
                            for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                continue;
                            }
                        }
                    }
                }
            } else {//无并发数限制
                eleConcurrentNumNow.incrementAndGet();
                return true;
            }
        } else if(p_header.pckType == PacketType.EleQuery){
            if (this.frontEleQueryMaxCcCount > 0 && this.frontQueryMaxCcCount<=0) {//有并发数限制
                for (int i = 0; i < 3; i++) {//自旋3次，每次count 1000
                    int cc = this.eleQryConcurrentNumNow.get();
                    if (cc < this.frontEleQueryMaxCcCount) {
                        int newCcNum = cc + 1;
                        if (eleQryConcurrentNumNow.compareAndSet(cc, newCcNum)) {
                            return true;
                        } else {
                            for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                continue;
                            }
                        }
                    }
                }
            } else if (this.frontEleQueryMaxCcCount > 0) {//有并发数限制
                for (int i = 0; i < 3; i++) {//自旋3次，每次count 1000
                    int cc = this.eleQryConcurrentNumNow.get();
                    int dd = this.qryConcurrentNumNow.get();
                    if (cc<this.frontEleQueryMaxCcCount &&cc+ dd<this.frontQueryMaxCcCount) {
                        //先抢占资源，然后在判断是否可以使用资源
                        int newCcNum = cc + 1;
                        if (eleQryConcurrentNumNow.compareAndSet(cc, newCcNum)) {
                            if(newCcNum+this.qryConcurrentNumNow.get()<=this.frontQueryMaxCcCount) {
                                return true;
                            }else {
                                eleQryConcurrentNumNow.decrementAndGet();
                                for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                    continue;
                                }
                            }
                        } else {
                            for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                continue;
                            }
                        }
                    }
                }
            }else {//无并发数限制
                eleQryConcurrentNumNow.incrementAndGet();
                return true;
            }
        }else {
            if (this.frontQueryMaxCcCount > 0 && this.frontEleQueryMaxCcCount <= 0) {//有并发数限制
                for (int i = 0; i < 3; i++) {//自旋3次，每次count 1000
                    int cc = this.qryConcurrentNumNow.get();
                    if (cc < this.frontQueryMaxCcCount) {
                        int newCcNum = cc + 1;
                        if (qryConcurrentNumNow.compareAndSet(cc, newCcNum)) {
                            return true;
                        } else {
                            for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                continue;
                            }
                        }
                    }
                }
            } else if (this.frontQueryMaxCcCount > 0) {//有并发数限制
                for (int i = 0; i < 3; i++) {//自旋3次，每次count 1000
                    int cc = this.eleQryConcurrentNumNow.get();
                    int dd = this.qryConcurrentNumNow.get();
                    if (cc+ dd<this.frontEleQueryMaxCcCount) {
                        //先抢占资源，然后在判断是否可以使用资源
                        int newDdNum = dd + 1;
                        if (qryConcurrentNumNow.compareAndSet(dd, newDdNum)) {
                            if(newDdNum+this.eleQryConcurrentNumNow.get()<=this.frontQueryMaxCcCount) {
                                return true;
                            }else {
                                qryConcurrentNumNow.decrementAndGet();
                                for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                    continue;
                                }
                            }
                        } else {
                            for (int j = 0; j < 1000; j++) {//自旋，每次count 1000
                                continue;
                            }
                        }
                    }
                }
            } else {//无并发数限制
                qryConcurrentNumNow.incrementAndGet();
                return true;
            }
        }
        return false;
    }
    
    //最新一次执行时间
    public Date lastExecPayTime;
    public Date lastExecPayQryTime;
    public Date lastExecEleTime;
    public Date lastExecEleQryTime;
    public Date lastExecOtherTime;
    
    /**
     * 设置最新一次执行时间
     */
    public void setLastExecTime(ReqRespHeader pHeader) {
        if (pHeader.pckType == PacketType.Pay) {
            lastExecPayTime = new Date();
        }else if (pHeader.pckType == PacketType.PayQuery) {
        	lastExecPayQryTime = new Date();
        }else if (pHeader.pckType == PacketType.Ele) {
        	lastExecEleTime = new Date();
        }else if (pHeader.pckType == PacketType.EleQuery) {
        	lastExecEleQryTime = new Date();
        }else {
        	lastExecOtherTime = new Date();
        }
    }
    
    //最后一次释放时间
    public Date lastReleasePayTime;
    public Date lastReleasePayQryTime;
    public Date lastReleaseEleTime;
    public Date lastReleaseEleQryTime;
    public Date lastReleaseOtherTime;

    /**
     * 释放资源，释放由allocate()分配的资源
     */
    public void release(ReqRespHeader p_header) {
        if (p_header.pckType == PacketType.Pay) {
            payConcurrentNumNow.decrementAndGet();
            lastReleasePayTime = new Date();
        }else if (p_header.pckType == PacketType.Ele) {
            eleConcurrentNumNow.decrementAndGet();
            lastReleaseEleTime = new Date();
        }else if (p_header.pckType == PacketType.EleQuery) {
            eleQryConcurrentNumNow.decrementAndGet();
            lastReleaseEleQryTime = new Date();
        } else {
            qryConcurrentNumNow.decrementAndGet();
            if (p_header.pckType == PacketType.PayQuery) {
            	lastReleasePayQryTime = new Date();
            }else{
            	lastReleaseOtherTime = new Date();
            }
        }
    }

    /**获取状态描述*/
    public String getFrontStatusDesc(){
    	if(frontStatus == null || frontStatus.status == null){
    		return "未初始";
    	}else if(frontStatus.status.equals(EnBfStatus.init)){
    		return "初始";
    	}else if(frontStatus.status.equals(EnBfStatus.normal)){
    		return "正常";
    	}else if(frontStatus.status.equals(EnBfStatus.exception)){
    		return "异常";
    	}else{
    		return "未知";
    	}
    }

    /**
     * 取ip和端口或者url，给监测用
     */
    public String getIpPortOrUrl() {
        if (StringHelper.hasAnyChar(serverIP) && StringHelper.hasAnyChar(serverPort)) {
            return serverIP + ":" + serverPort;
        } else {
            return serverURL;
        }
    }

    public void pingServer() {

        String oriServerUrl = getIpPortOrUrl().trim();
        String srvUrl = oriServerUrl.replace("http://", "").replace("https://", "");
        srvUrl = StringHelper.trimStart(srvUrl, "/");
        int indx = srvUrl.indexOf("/");
        if (indx > 0) {
            srvUrl = srvUrl.substring(0, indx);
        }
        String[] ipAndPort = srvUrl.split(":");
        String ip = ipAndPort[0];
        int port = 0;
        if (ipAndPort.length > 1 && ipAndPort[1].length() > 0) {
            port = Integer.parseInt(ipAndPort[1]);
        } else if (ipAndPort.length == 1 && oriServerUrl.startsWith("http")) {
            port = 80;
        } else if (ipAndPort.length == 1 && oriServerUrl.startsWith("https")) {
            port = 443;
        }
        if (port <= 0) {
            frontStatus.status = EnBfStatus.exception;
            frontStatus.statusTime = new Date();
            frontStatus.statusInfo = "服务地址有误，取不到端口号";
        } else {
            try {
                Socket socket = new Socket(ip, port);
                socket.close();
                socket = null;
                frontStatus.status = EnBfStatus.normal;
                frontStatus.statusTime = new Date();
                frontStatus.statusInfo = "连接正常";
            } catch (Exception e) {
                frontStatus.status = EnBfStatus.exception;
                frontStatus.statusTime = new Date();
                frontStatus.statusInfo = e.getMessage();
            }

        }
    }

    public FtpSet getFtpSet(String p_for) {
        if (hashFtpSet != null) {
            if (hashFtpSet.containsKey(p_for)) {
                return hashFtpSet.get(p_for);
            } else if (hashFtpSet.containsKey("*")) {
                return hashFtpSet.get("*");
            }
        }
        return null;
    }

    public Object[] getToken(String appid) {
        if (hashToken == null) {
            hashToken=    new ConcurrentHashMap<String,Object[]>();
        }
        if (hashToken.containsKey(appid)) {
            return hashToken.get(appid);
        } else {
            return null;
        }
    }

    public void setToken(String appid,Object[] tokenArray) {
        if (hashToken == null) {
            hashToken=    new ConcurrentHashMap<String,Object[]>();
        }
        hashToken.put(appid, tokenArray);
    }

    public ConnSet getConnSet(String p_for) {
        if (hashConnSet != null) {
            if (hashConnSet.containsKey(p_for)) {
                return hashConnSet.get(p_for);
            } else if (hashConnSet.containsKey("*")) {
                return hashConnSet.get("*");
            }
        }
        return null;
    }

    public String getUrl(String p_for) {
        if (hashServerURL != null) {
            if (hashServerURL.containsKey(p_for)) {
                return hashServerURL.get(p_for);
            }
        }
        return null;
    }

    public void addUrl(String p_for, String p_url) {
        if (hashServerURL == null) {
            hashServerURL = new HashMap<String, String>();
        }
        hashServerURL.put(p_for, p_url);
    }

    private void setSupportTransType(String p_value) {
        supportTransType = p_value;
        if (StringHelper.hasAnyChar(supportTransType)) {
            supportTransType = supportTransType.trim();
            String[] tsTypes = supportTransType.split(",");
            HashMap<String, String> map = new HashMap<String, String>();
            for (int i = 0; i < tsTypes.length; i++) {
                if (tsTypes[i].trim().length() > 0) {
                    map.put(tsTypes[i].trim().toLowerCase(), tsTypes[i].trim());
                }
            }
            mapSupport = map;
        }
    }

    private void setNonSupportTransType(String p_value) {
        nonSupportTransType = p_value;
        if (StringHelper.hasAnyChar(nonSupportTransType)) {
            nonSupportTransType = nonSupportTransType.trim();
            String[] tsTypes = nonSupportTransType.split(",");
            HashMap<String, String> map = new HashMap<String, String>();
            for (int i = 0; i < tsTypes.length; i++) {
                if (tsTypes[i].trim().length() > 0) {
                    map.put(tsTypes[i].trim().toLowerCase(), tsTypes[i].trim());
                }
            }
            mapNonSupport = map;
        }
    }

    /**
     * 判断前置机是否支持该指令类型
     */
    public boolean isSupport(String p_transType) {
        if (StringHelper.hasAnyChar(p_transType)) {
            String chkTransType = p_transType.toLowerCase();
            if (mapNonSupport != null && mapNonSupport.size() > 0) {
                if (mapNonSupport.containsKey(chkTransType)) {
                    return false;
                }
            }
            if (mapSupport != null && mapSupport.size() > 0) {
                if (!mapSupport.containsKey(chkTransType)) {
                    return false;
                }
            }
        }
        return true;
    }

    public void fromResultSet(ResultSet p_RS) throws Exception {
        urid = p_RS.getString("urid");
        bankCode = p_RS.getString("bicode");
        corporation = p_RS.getString("bicorp");
        group = p_RS.getString("bigroup");
        code = p_RS.getString("bfcode");
        name = p_RS.getString("bfname");
        serverIP = p_RS.getString("bfip");
        serverPort = p_RS.getString("bfservp");
        signPort = p_RS.getString("bfsecup");
        filePort = p_RS.getString("bffilep");
        payQueueCount = p_RS.getInt("bipqc");
        payQueryQueueCount = p_RS.getInt("bipqqc");
        elseQueuecount = p_RS.getInt("bieqc");
        frontPayMaxCcCount = p_RS.getInt("bfpsc");
        frontQueryMaxCcCount = p_RS.getInt("bfqsc");
        frontPriority = p_RS.getInt("bfp");
        setSupportTransType(p_RS.getString("bfsupp"));
        setNonSupportTransType(p_RS.getString("bfnon"));
        Map<String, String> tmpMap = new HashMap<String, String>();
        tmpMap.put(p_RS.getString("bfskey"), p_RS.getString("bfsvalue"));

        HashMap<String, Map<String, String>> tmpFrontSet = new HashMap<String, Map<String, String>>();
        tmpFrontSet.put(p_RS.getString("bfstype"), tmpMap);
        frontSet = tmpFrontSet;

    }

    private void addStrValueByFor(XElement p_XE) {
        HashMap<String, String> theMap = new HashMap<String, String>();

        ArrayList<XElement> xeList = p_XE.getAllChildList();
        if (xeList != null && xeList.size() > 0) {
            for (int i = 0; i < xeList.size(); i++) {
                String eachFor = xeList.get(i).getAttrValue("for");
                if (eachFor == null) {
                    eachFor = "";
                }
                String eachKey = xeList.get(i).name + "-" + eachFor;
                theMap.put(eachKey, xeList.get(i).innerText.replace("{$DSPHOME}", FGBiz.DSPHOME));
            }
        }
        mapStrValueByFor = theMap;
    }

    /**
     * 按for查找
     */
    public String getStrValueByFor(String p_name, String p_for) {
        if (mapStrValueByFor != null) {
            String theKey = p_name + "-" + p_for;
            if (mapStrValueByFor.containsKey(theKey)) {
                return mapStrValueByFor.get(theKey);
            }
        }
        return null;
    }

    public void fromXElement(XElement p_XE) throws Exception {
        addStrValueByFor(p_XE);

        String payCcCount = p_XE.getSingleTextNotNull("frontPayMaxCcCount");
        if (StringHelper.hasAnyChar(payCcCount)) {
            frontPayMaxCcCount = Integer.valueOf(payCcCount);
        }

        String qryCcCount = p_XE.getSingleTextNotNull("frontQueryMaxCcCount");
        if (StringHelper.hasAnyChar(qryCcCount)) {
            frontQueryMaxCcCount = Integer.valueOf(qryCcCount);
        }

        String eleCcCount = p_XE.getSingleTextNotNull("frontEleMaxCcCount");
        if (StringHelper.hasAnyChar(eleCcCount)) {
            frontEleMaxCcCount = Integer.valueOf(eleCcCount);
        }

        String eleQryCcCount = p_XE.getSingleTextNotNull("frontEleQueryMaxCcCount");
        if (StringHelper.hasAnyChar(eleQryCcCount)) {
            frontEleQueryMaxCcCount = Integer.valueOf(eleQryCcCount);
        }
        useDirectchannelJarFile = p_XE.getSingleTextNotNull("useDirectchannelJarFile");
        urid = p_XE.getSingleTextNotNull("urid");
        bankCode = p_XE.getSingleTextNotNull("bankCode");//DomHelper.getSingleElementInnerText(p_XE, "bankCode");
        corporation = p_XE.getSingleTextNotNull("corporation");//DomHelper.getSingleElementInnerText(p_XE, "corporation");
        group = p_XE.getSingleTextNotNull("group");//DomHelper.getSingleElementInnerText(p_XE, "group");
        tenant = p_XE.getSingleTextNotNull("tenant");
        code = p_XE.getSingleTextNotNull("code");//DomHelper.getSingleElementInnerText(p_XE, "code");
        name = p_XE.getSingleTextNotNull("name");//DomHelper.getSingleElementInnerText(p_XE, "name");
        serverIP = p_XE.getSingleTextNotNull("serverIP");//DomHelper.getSingleElementInnerText(p_XE, "serverIP");
        serverPort = p_XE.getSingleTextNotNull("serverPort");//DomHelper.getSingleElementInnerText(p_XE, "serverPort");
        signPort = p_XE.getSingleTextNotNull("signPort");//DomHelper.getSingleElementInnerText(p_XE, "signPort");
        filePort = p_XE.getSingleTextNotNull("filePort");
        org = p_XE.getSingleTextNotNull("org");//DomHelper.getSingleElementInnerText(p_XE, "org");
        loginFlag = p_XE.getSingleTextNotNull("loginFlag");//DomHelper.getSingleElementInnerText(p_XE, "loginFlag");
        protocolNo = p_XE.getSingleTextNotNull("protocolNo");
        corpNo = p_XE.getSingleTextNotNull("corpNo");
        keyID = p_XE.getSingleTextNotNull("keyID");//DomHelper.getSingleElementInnerText(p_XE, "keyID");
        loginName = p_XE.getSingleTextNotNull("loginName");//DomHelper.getSingleElementInnerText(p_XE, "loginName");
        serverURL = p_XE.getSingleTextNotNull("serverURL").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "serverURL");
        signURL = p_XE.getSingleTextNotNull("signURL").replaceAll("\r|\n|\t", "");

        loginPasswd = p_XE.getSingleTextNotNull("loginPasswd");//DomHelper.getSingleElementInnerText(p_XE, "loginPasswd");
        String syncToken = p_XE.getSingleTextNotNull("syncTokenFromMasterHost").toLowerCase();
        if("true".equals(syncToken) || "1".equals(syncToken)){
        	syncTokenFromMasterHost = true;
        }

        oppCertFilePath = com.fingard.dsp.DSPSet.replaceFilePath(p_XE.getSingleTextNotNull("oppCertFilePath").replaceAll("\r|\n|\t", ""));
        ownKeyStorePath = com.fingard.dsp.DSPSet.replaceFilePath(p_XE.getSingleTextNotNull("ownKeyStorePath").replaceAll("\r|\n|\t", ""));
        ownKeyPassword = p_XE.getSingleTextNotNull("ownKeyPassword").replaceAll("\r|\n|\t", "");
        
        ownPrivateKeyXmlFilePath = com.fingard.dsp.DSPSet.replaceFilePath(p_XE.getSingleTextNotNull("ownPrivateKeyXmlFilePath").replaceAll("\r|\n|\t", ""));
        oppPublicKeyXmlFilePath = com.fingard.dsp.DSPSet.replaceFilePath(p_XE.getSingleTextNotNull("oppPublicKeyXmlFilePath").replaceAll("\r|\n|\t", ""));
        
        operator = p_XE.getSingleTextNotNull("operator");//DomHelper.getSingleElementInnerText(p_XE, "operator");
        termid = p_XE.getSingleTextNotNull("termid");//DomHelper.getSingleElementInnerText(p_XE, "termid");
        
        serverCode = p_XE.getSingleTextNotNull("serverCode");
        
        bkTransFolder = p_XE.getSingleTextNotNull("bkTransFolder").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "bkTransFolder");
        accessBkFileMode = p_XE.getSingleTextNotNull("accessBkFileMode").replaceAll("\r|\n|\t", "");
        dspFileServer = p_XE.getSingleTextNotNull("dspFileServer").replaceAll("\r|\n|\t", "");
        bkPayFolder = p_XE.getSingleTextNotNull("bkPayFolder").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "bkPayFolder");
        bkRecFolder = p_XE.getSingleTextNotNull("bkRecFolder").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "bkRecFolder");
        bkQryPayFolder = p_XE.getSingleTextNotNull("bkQryPayFolder").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "bkPayFolder");
        bkQryRecFolder = p_XE.getSingleTextNotNull("bkQryRecFolder").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "bkRecFolder");
        bkQryEleFolder = p_XE.getSingleTextNotNull("bkQryEleFolder").replaceAll("\r|\n|\t", "");
        serverUpload = p_XE.getSingleTextNotNull("serverUpload").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "serverUpload");
        serverDownload = p_XE.getSingleTextNotNull("serverDownload").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "serverDownload");

        userName = p_XE.getSingleTextNotNull("userName").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "userName");
        userPassword = p_XE.getSingleTextNotNull("userPassword").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "userPassword");
        folderForRemoteHost = p_XE.getSingleTextNotNull("folderForRemoteHost").replaceAll("\r|\n|\t", "");//DomHelper.getSingleElementInnerText(p_XE, "folderForRemoteHost");
        bankReceiptMainDir = p_XE.getSingleTextNotNull("bankReceiptMainDir").replaceAll("\r|\n|\t", "");
        setSupportTransType(p_XE.getSingleTextNotNull("supportTransType").replaceAll("\r|\n|\t", ""));
        setNonSupportTransType(p_XE.getSingleTextNotNull("nonSupportTransType").replaceAll("\r|\n|\t", ""));

        checkLevel=p_XE.getSingleTextNotNull("checkLevel");
        ArrayList<XElement> ftpList = p_XE.getChildList("ftpSet");
        if (ftpList != null && ftpList.size() > 0) {
            HashMap<String, FtpSet> tmpHashFtpSet = new HashMap<String, FtpSet>();
            for (int i = 0; i < ftpList.size(); i++) {
                String eachFor = ftpList.get(i).getAttrValue("for");
                if (eachFor == null) {
                    eachFor = "";
                }
                FtpSet eachFtpSet = new FtpSet();
                eachFtpSet.fromXElement(ftpList.get(i));
                tmpHashFtpSet.put(eachFor, eachFtpSet);
            }
            hashFtpSet = tmpHashFtpSet;
        }

        HashMap<String, ConnSet> tmpHashSet = null;
        ArrayList<XElement> connList = p_XE.getChildList("connSet");
        if (connList != null && connList.size() > 0) {
            tmpHashSet = new HashMap<String, ConnSet>();
            for (int i = 0; i < connList.size(); i++) {
                String eachFor = connList.get(i).getAttrValue("for");
                if (eachFor == null) {
                    eachFor = "";
                }
                ConnSet eachConnSet = new ConnSet();
                eachConnSet.fromXElement(connList.get(i));
                tmpHashSet.put(eachFor, eachConnSet);
            }
        }
        hashConnSet = tmpHashSet;

        ArrayList<XElement> urlList = p_XE.getChildList("serverURL");
        if (urlList != null && urlList.size() > 0) {
            for (int i = 0; i < urlList.size(); i++) {
                String eachFor = urlList.get(i).getAttrValue("for");
                if (eachFor == null) {
                    eachFor = "";
                }

                addUrl(eachFor, urlList.get(i).innerText.replaceAll("\r|\n|\t", ""));
            }
        }


        HashMap<String, ListenerSet> tmpListenerSet = null;
        ArrayList<XElement> listenerList = p_XE.getChildList("listenerSet");
        if (listenerList != null && listenerList.size() > 0) {
            tmpListenerSet = new HashMap<String, ListenerSet>();
            for (int i = 0; i < listenerList.size(); i++) {
                String eachFor = listenerList.get(i).getAttrValue("for");
                if (eachFor == null) {
                    eachFor = i + "";
                }
                ListenerSet eachListenerSet = new ListenerSet();
                eachListenerSet.fromXElement(listenerList.get(i));
                eachListenerSet.bankFront = this;
                tmpListenerSet.put(eachFor, eachListenerSet);
            }
        }
        hashListenerSet = tmpListenerSet;

        HashMap<String, TaskTimerSet> tmpTimerList = null;
        ArrayList<XElement> timerList = p_XE.getChildList("taskTimer");
        if (timerList != null && timerList.size() > 0) {
            tmpTimerList = new HashMap<String, TaskTimerSet>();
            for (int i = 0; i < timerList.size(); i++) {
                String eachFor = timerList.get(i).getAttrValue("for");
                if (eachFor == null) {
                    eachFor = i + "";
                }
                TaskTimerSet eachTimerSet = new TaskTimerSet();
                eachTimerSet.fromXElement(timerList.get(i));
                eachTimerSet.bankFront = this;
                tmpTimerList.put(eachFor, eachTimerSet);
            }
        }
        hashTimerSet = tmpTimerList;
    }

    public void compatible() {
        if (frontSet != null && frontSet.containsKey("FixSet")) {
            Map<String, String> tmpMap = frontSet.get("FixSet");
            org = tmpMap.get("Org");
            loginFlag = tmpMap.get("LoginFlag");
            protocolNo = tmpMap.get("ProtocolNo");
            keyID = tmpMap.get("KeyID");
            loginName = tmpMap.get("LoginName");
            serverURL = tmpMap.get("ServerURL");
            signURL = tmpMap.get("SignURL");
            loginPasswd = tmpMap.get("LoginPasswd");
            operator = tmpMap.get("Operator");
            termid = tmpMap.get("Termid");
            if(tmpMap.containsKey("ServerCode")){
            	serverCode = tmpMap.get("ServerCode");
            }
            bkTransFolder = tmpMap.get("BkTransFolder");
            accessBkFileMode = tmpMap.get("AccessBkFileMode");
            dspFileServer = tmpMap.get("DspFileServer");
            bkPayFolder = tmpMap.get("BkPayFolder");
            bkRecFolder = tmpMap.get("BkRecFolder");
            bkQryPayFolder = tmpMap.get("BkQryPayFolder");
            bkQryRecFolder = tmpMap.get("BkQryRecFolder");
            bkQryEleFolder  = tmpMap.get("BkQryEleFolder");
            folderForRemoteHost = tmpMap.get("FolderForRemoteHost");
            serverUpload = tmpMap.get("ServerUpload");
            serverDownload = tmpMap.get("ServerDownload");
            userName = tmpMap.get("UserName");
            userPassword = tmpMap.get("UserPassword");
        }
    }

    //目前只支持单节点赋值及上级赋值下级共享方式  重复节点的情况占不能处理hashmap不允许重复
    public Map<String, String> decrypt(XElement p_xe) {
        try {
            ArrayList<XElement> arrayList = p_xe.getAllChildList();
            for (int i = 0; i < arrayList.size(); i++) {
                String encrypt = arrayList.get(i).getAttrValue("encrypt");
                //生成的密钥:AES密文#密钥(base64)#(原文#密钥(base64))做md5加盐摘要（并校验）
                String data = arrayList.get(i).innerText;
                int count = arrayList.get(i).countChildren();
                if (encrypt.equals("true")) {
                    String deData = "";
                    if (count == 0) {
                        if (!StringHelper.isNullOrEmpty(data)) {
                            if (data.indexOf("#") != -1) {
                                String encryptData = data.substring(0, data.indexOf("#"));
                                String baseKey = data.substring(data.indexOf("#") + 1, data.lastIndexOf("#"));
                                String md5Data = data.substring(data.lastIndexOf("#") + 1);
                                String trueKey = new String(new BASE64Decoder().decodeBuffer(baseKey));
                                deData = new String(AESHelper.decodeAES(trueKey.getBytes(), new BASE64Decoder().decodeBuffer(encryptData)));
                                if (MD5SaltHelper.verify(deData + "#" + new BASE64Encoder().encode(trueKey.getBytes()), md5Data)) {
                                    decrypt.put(arrayList.get(i).name, deData);
                                }
                            }
                        }
                    } else if (count > 0) {//下级节点共享
                        ArrayList<XElement> xElementArrayList = arrayList.get(i).getAllChildList();
                        for (int j = 0; j < xElementArrayList.size(); j++) {
                            if ("".equals(xElementArrayList.get(j).getAttrValue("encrypt"))) {
                                xElementArrayList.get(j).addAttr("encrypt", "true");
                            }
                        }
                        decrypt(arrayList.get(i));
                    }
                } else {//上级节点不加密下级某节点加密
                    if (count > 0) {
                        decrypt(arrayList.get(i));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decrypt;
    }

    public void setDecrypt() {
        try {
            if (decrypt != null) {
                for (Map.Entry<String, String> entry : decrypt.entrySet()) {
                    Field[] fields = this.getClass().getDeclaredFields();
                    for (int i = 0; i < fields.length; i++) {
                        fields[i].setAccessible(true);
                        if (fields[i].getName().equals(entry.getKey())) {
                            fields[i].set(this, fields[i].getType().getConstructor(fields[i].getType()).newInstance(entry.getValue()));
                        }
                    }
                    if (hashListenerSet != null) {
                        for (Map.Entry<String, ListenerSet> listenerSetEntry : hashListenerSet.entrySet()) {
                            Field[] field = listenerSetEntry.getValue().getClass().getDeclaredFields();
                            for (int i = 0; i < field.length; i++) {
                                if (field[i].getName().equals(entry.getKey())) {
                                    field[i].set(listenerSetEntry.getValue(), field[i].getType().getConstructor(field[i].getType()).newInstance(entry.getValue()));
                                }
                            }
                        }
                    }
                    if (hashConnSet != null) {
                        for (Map.Entry<String, ConnSet> connSetEntry : hashConnSet.entrySet()) {
                            Field[] field = connSetEntry.getValue().getClass().getDeclaredFields();
                            for (int i = 0; i < field.length; i++) {
                                if (field[i].getName().equals(entry.getKey())) {
                                    field[i].set(connSetEntry.getValue(), field[i].getType().getConstructor(field[i].getType()).newInstance(entry.getValue()));
                                }
                            }
                        }
                    }
                    if (hashFtpSet != null) {
                        for (Map.Entry<String, FtpSet> ftpSetEntry : hashFtpSet.entrySet()) {
                            Field[] field = ftpSetEntry.getValue().getClass().getDeclaredFields();
                            for (int i = 0; i < field.length; i++) {
                                if (field[i].getName().equals(entry.getKey())) {
                                    field[i].set(ftpSetEntry.getValue(), field[i].getType().getConstructor(field[i].getType()).newInstance(entry.getValue()));
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
